package com.ruoyi.framework.mdc;

import com.ruoyi.common.utils.uuid.UUID;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 链路追踪过滤器 每次调用都会生成新的链路追踪ID
 *
 * @Author： Lonni
 * @Date： 2025/9/9  15:19
 */
@Component
@Slf4j
public class TraceFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {
        log.info("进入链路跟踪过滤器=====>");
        // 尝试从请求头获取Trace ID，如果没有则生成新的
        String traceId = request.getHeader(MdcConstain.TRACE_ID_HEADER);
        if (traceId == null || traceId.isEmpty()) {
            traceId = UUID.randomUUID().toString();
        }

        // 生成Span ID
        String spanId = UUID.randomUUID().toString();

        // 将跟踪信息放入MDC
        MDC.put(MdcConstain.TRACE_ID, traceId);
        MDC.put(MdcConstain.SPAN_ID, spanId);
        log.info("链路跟踪信息: traceId={}, spanId={}", traceId, spanId);
        // 将Trace ID添加到响应头，方便前端跟踪
        response.addHeader(MdcConstain.TRACE_ID_HEADER, traceId);
        try {
            filterChain.doFilter(request, response);
        } finally {
            // 请求完成后清理MDC
            MDC.clear();
            log.info("链路跟踪过滤器=====>链路跟踪信息清理完成");
        }
    }
}
